/*
Autor: Alexander Savochkin, 2010-2013
New BSD License
*/

#include "FactoriesKeeper.h"
#include "Exception.h"

namespace SRCLF {

using Config::Section;

	FactoriesKeeper::FactoriesKeeper()
	{
	}

	FactoriesKeeper::~FactoriesKeeper()
	{
		for(map<string, RegulatorFactory* >::iterator ir = regulator_factories.begin();
			ir != regulator_factories.end(); ++ir)
			delete ir->second;

		for(map<string, OperatedInputFactory* >::iterator ii = operated_input_factories.begin();
			ii != operated_input_factories.end(); ++ii )
			delete ii->second;

		for(map<string, OperatedOutputFactory* >::iterator io = operated_output_factories.begin();
			io != operated_output_factories.end(); ++io)
			delete io->second;
	}

	FactoriesKeeper& FactoriesKeeper::getInstance()
	{
		static FactoriesKeeper instance;
		return instance;
	}

	bool FactoriesKeeper::registerRegulatorFactory(const string& name, RegulatorFactory *factory)
	{
		if( regulator_factories.find(name) != regulator_factories.end() )
			//factory with same name already registered
			return false;

		regulator_factories[name] = factory;
		return true;
	}

	bool FactoriesKeeper::registerInputFactory(const string& name, OperatedInputFactory *factory)
	{
		if( operated_input_factories.find(name) != operated_input_factories.end() )
			//factory with same name already registered
			return false;


		operated_input_factories[name] = factory;
		return true;
	}

	bool FactoriesKeeper::registerOutputFactory(const string& name, OperatedOutputFactory *factory)
	{
		if( operated_output_factories.find(name) != operated_output_factories.end() )
			//factory with same name already registered
			return false;

		operated_output_factories[name] = factory;
		return true;
	}


	OperatedInputFactory* FactoriesKeeper::getInputFactory(const string& object_registered_type_name)
	{
		map<string, OperatedInputFactory* >::iterator it = operated_input_factories.find(object_registered_type_name);
		if (it == operated_input_factories.end()) 
			throw Exception("Unknown input factory name: " + object_registered_type_name);
		return it->second;
	}

	OperatedOutputFactory* FactoriesKeeper::getOutputFactory(const string& object_registered_type_name)
	{
		map<string, OperatedOutputFactory* >::iterator it = operated_output_factories.find(object_registered_type_name);
		if (it == operated_output_factories.end()) 
			throw Exception("Unknown output factory name: " + object_registered_type_name);
		return it->second;
	}

	RegulatorFactory* FactoriesKeeper::getRegulatorFactory(const string& object_registered_type_name)
	{
		map<string, RegulatorFactory* >::iterator it = regulator_factories.find(object_registered_type_name);
		if (it == regulator_factories.end()) 
			throw Exception("Unknown regulator factory name: " + object_registered_type_name);
		return it->second;
	}

	IOperatedInput* FactoriesKeeper::newInputInstance(const string& section_name, const Configuration& config)
	{
		//BOOST_LOG_SEV(logger, notification) << "Creating input with name '" << section_name << "'";
		const Section& section = config.getSection(Section::input, section_name);
		string input_class = section.getClassName();
		string input_name = section.getName();
		return getInputFactory(input_class)->newInstance(input_name, config);
	}

	IOperatedOutput* FactoriesKeeper::newOutputInstance(const string& section_name, const Configuration& config)
	{
		//BOOST_LOG_SEV(logger, notification) << "Creating output with name '" << section_name << "'";
		const Section& section = config.getSection(Section::output, section_name);
		string output_class = section.getClassName();
		string output_name = section.getName();
		return getOutputFactory(output_class)->newInstance(output_name, config);
	}

	IRegulator* FactoriesKeeper::newRegulatorInstance(const string& section_name, const Configuration& config)
	{
		//BOOST_LOG_SEV(logger, notification) << "Creating regulator with name '" << section_name << "'";
		const Section& section = config.getSection(Section::regulator, section_name);
		string regulator_class = section.getClassName();
		string regulator_name = section.getName();
		return getRegulatorFactory(regulator_class)->newInstance(regulator_name, config);
	}


} //namespace SRCLF
